﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Threading;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Xml;
using System.Reflection;

using DnPakExplorer.Controls;

namespace DnPakExplorer.Forms {
	public partial class EquipmentStoreViewerForm : FormBase {
		PakExplorer mPakExplorer;
		ItemAdapter mAdapter;
		List<IItem> mItemList = null;
		Hashtable mBufferedSetEntries = new Hashtable();
		InfoOverlayForm mInfoForm;
		Regex mStateVlauePettern = new Regex(@"-?\d*\.?\d+$");
		ContextMenuStrip mJobMenu;
		ContextMenuStrip mConextMenu;
		List<TableEntry> mTables;
		int mSelectedJob;
		TableEntry mSelectedTableEntry;

		public EquipmentStoreViewerForm(PakExplorer pakExplorer) {
			InitializeComponent();

			SetStyle(ControlStyles.ResizeRedraw, true);

			Util.LoadTables();

			this.MaximumSize = new System.Drawing.Size(Screen.PrimaryScreen.WorkingArea.Width, Screen.PrimaryScreen.WorkingArea.Height-20);
			listGridView1.OnGridHover = OnItemHover;
			listGridView1.MouseDown += listGridView1_MouseDown;
			listGridView1.MinColumnWidth = 70;
			listGridView1.MinRowHeight = 56;
			textBox1.TextBox.PreviewKeyDown += textBox1_PreviewKeyDown;
			mPakExplorer = pakExplorer;
			mTables = new List<TableEntry>();
			foreach (XmlNode node in DnResourceUtil.Config.SelectNodes(@"/Config/ItemTables/Table")) {
				mTables.Add(new TableEntry(node.Attributes.GetNamedItem("name").InnerText, node.Attributes.GetNamedItem("path").InnerText));
			}
			mTables.Add(new TableEntry("全部", ""));
			SelectTable(mTables[mTables.Count - 1]);
			SelectJob(0);
			mJobMenu = CreateJobSelectMenu();
			mAdapter = new ItemAdapter();
			listGridView1.SetAdapter(mAdapter);
		}

		void listGridView1_MouseDown(object sender, MouseEventArgs e) {
			InfoOverlayForm.HideItem();
		}

		private void SelectTable(TableEntry entry) {
			mSelectedTableEntry = entry;
			spriteButtom2.Text = entry.name;
		}

		private void SelectJob(int jobId) {
			mSelectedJob = jobId;
			if (jobId>0) {
				spriteButtom1.Text = DnResourceUtil.GetJobName(jobId);
			} else {
				spriteButtom1.Text = "所有职业";
			}
			
		}

		public List<IItem> GetItems() {
			return mItemList;
		}


		private void OnContextMenu(object sender, EventArgs e) {
			ToolStripItem menu = sender as ToolStripItem;
			if (menu.Text == "放入背包") {
				Item item = (menu.Tag as Item);
				IUserItem userItem = new UserItem(item.fromTable, item.row);
				if (new ItemEdtorForm(userItem).ShowDialog(this) == System.Windows.Forms.DialogResult.OK) {
					Character ch = DnPlayerUtil.CurrentCharacter;
					if (ch != null) {
						ch.BagPanel.AddItem(userItem);
					}
				}
			}else if (menu.Text == "复制物品ID") {
				Item item = (menu.Tag as Item);
				Clipboard.SetDataObject(item.id.ToString(), true);
			}
		}


		private void ListGridView_MouseClick(object sender, MouseEventArgs e) {
			if (e.Button == System.Windows.Forms.MouseButtons.Right) {
				mConextMenu = new ContextMenuStrip();
				mConextMenu.Renderer = new ContextMenuStripRenderer();
				Point pointIndex = listGridView1.PointToCellIndex(e.Location);
				if (pointIndex.Y >= 0 && pointIndex.X >= 0) {
					ToolStripItem m = mConextMenu.Items.Add("放入背包", null, OnContextMenu);
					m.Tag = mItemList[pointIndex.Y];
					m.Enabled = DnPlayerUtil.CurrentCharacter != null;
					mConextMenu.Items.Add("复制物品ID", null, OnContextMenu).Tag = mItemList[pointIndex.Y];
					mConextMenu.Show(Cursor.Position);
					InfoOverlayForm infoForm = InfoOverlayForm.GetOrCreateItemInfoForm();
					if (infoForm.Visible)
						infoForm.Hide();
				}
			}
		}


		public void OnItemHover(int row, int column) {
			if (row >=0 && column==0 && (mConextMenu==null || !mConextMenu.Visible)) {
				IItem item = mItemList[row];
				mInfoForm = InfoOverlayForm.GetOrCreateItemInfoForm();
				if (mInfoForm.Item != item) {
					mInfoForm.Item = item;
				}

				mInfoForm.UpdateInfoFormPosition();
				listGridView1.Capture = true;
				if (!mInfoForm.Visible) {
					mInfoForm.Show();
				}
			} else {
				listGridView1.Capture = false;
				if (mInfoForm != null) {
					mInfoForm.Hide();
					mInfoForm = null;
				}
			}
		}

		

		

		public class ItemAdapter : ListGridAdapter{
			List<IItem> mList;
			List<KeyValuePair<int, int>> mAdustedRowHeight = new List<KeyValuePair<int, int>>();
			char[] mJobSpliter = new char[] { ';' };
			bool mTmpDrawnJobIcon;

			public override void OnDrawGridBackground(ListGridView view, Graphics g, Color color, int row, int column, Rectangle rect) {
				base.OnDrawGridBackground(view, g, color, row, column, rect);
				if (column == 0) {
					int iconSize = Math.Min(Math.Max(rect.Height - 6, 30), 50);
					Rectangle iconRect = new Rectangle(
						rect.X + 3,
						rect.Y + (rect.Height-iconSize)/2,
						iconSize,
						iconSize
					);
					Util.DrawItemImage(mList[row].iconId, iconRect, g);
					Util.DrawItemBox(mList[row].rank, iconRect, g);
					Util.DrawItemTags(mList[row], iconRect, g);
				} else if (column == 3) {
					int job = 0;
					mTmpDrawnJobIcon = false;
					string[] jobs = mList[row].needJobClass.Split(mJobSpliter, StringSplitOptions.RemoveEmptyEntries);
					if (jobs.Length==1) {
						job = int.Parse(jobs[0]);
					}
					if (job > 0) {
						int iconSize = 30;
						Rectangle iconRect = new Rectangle(
							rect.X + 3,
							rect.Y + (rect.Height-iconSize)/2,
							iconSize,
							iconSize
						);
						int iconid = Util.GetJobIconId(job);
						if (iconid >= 0) {
							mTmpDrawnJobIcon = true;
							Util.DrawJobIconPvP(g, iconRect, iconid);
						}
					}
				}
			}

			public override void OnDrawGrid(ListGridView view, Graphics g, string text, Color color, int row, int column, Rectangle rect) {
				if (column == 0) {
					int iconSize = Math.Min(Math.Max(rect.Height - 6, 30), 50);
					rect.Width = rect.Width - iconSize - 6;
					rect.X += iconSize + 3;
				} else if (column == 4 && !string.IsNullOrEmpty(text)) {
					//Region oldClip = g.Clip;
					//g.SetClip(rect);
					List<InfoOverlayForm.RichTextDrawBlock.RichString> richStrings;
					InfoOverlayForm.RichTextDrawBlock block = new InfoOverlayForm.RichTextDrawBlock(richStrings = InfoOverlayForm.RichTextDrawBlock.Measure(
					InfoOverlayForm.RichTextDrawBlock.Parse(text.Replace("\\n", "\n"), view.Font, color),
					g, view.StringFormat, new Rectangle(rect.X, rect.Y, rect.Width-6, rect.Height-6)));
					block.Position = new Point(rect.X+3, rect.Y+(rect.Height-block.Size.Height)/2);
					if (block.Size.Height+6 > rect.Height) {
						mAdustedRowHeight.Add(new KeyValuePair<int, int>(row, block.Size.Height+6));
					}
					
					block.Size = rect.Size;
					block.Draw(g);
					//g.Clip = oldClip;
					return;
				} else if (column == 3 && mTmpDrawnJobIcon) {
					int iconSize = 30;
					rect.Width = rect.Width - iconSize - 6;
					rect.X += iconSize + 3;
				}
				base.OnDrawGrid(view, g, text, color, row, column, rect);
			}

			public override void EndPaint(ListGridView view) {
				if (mAdustedRowHeight.Count>0) {
					foreach (KeyValuePair<int, int> value in mAdustedRowHeight) {
						view.SetRowHeight(value.Key, value.Value);
					}
					mAdustedRowHeight.Clear();
					view.NotifyDataChanged();
				}
			}

			public override int GetColumnWidth(int column) {
				switch (column) {
				case 0:
					return 200;
				case 1:
				case 2:
					return 50;
				case 3:
					return 85;
				case 4:
					return 330;
				default:
					return base.GetColumnWidth(column);
				}
			}

			public override int GetRowHeight(int row) {
				return base.GetRowHeight(row);
			}


			public void SetItems(List<IItem> items) {
				mList = items;
			}

			public override int RowCount {
				get { return mList.Count; }
			}

			public override int ColumnCount {
				get { return 6; }
			}

			public override void GetTopLeft(Grid drid) {
				drid.text = "物品id";
			}

			public override void GetGridData(int row, int column, Grid grid) {
				switch (column) {
				case 0:
					grid.text = mList[row].name;
					grid.textColor = Util.GetRankColor(mList[row].rank);
					break;
				case 1:
					grid.text = mList[row].limitLevel.ToString();
					break;
				case 2:
					grid.text = Util.GetRankText(mList[row].rank);
					break;
				case 3:
					if (mList[row].needJobClassName != null)
						grid.text = mList[row].needJobClassName;
					else
						grid.text = "";
					break;
				case 4:
					grid.text = mList[row].description;
					break;
				case 5:
					grid.text = mList[row].iconId.ToString();
					break;
				}
				
			}

			public override void GetRowHeader(int row, Grid grid) {
				grid.text = mList[row].id.ToString();
			}

			public override void GetColumnHeader(int column, Grid grid) {
				switch (column) {
				case 0:
					grid.text = "名称";
					break;
				case 1:
					grid.text = "等级限制";
					break;
				case 2:
					grid.text = "级别";
					break;
				case 3:
					grid.text = "职业";
					break;
				case 4:
					grid.text = "描述";
					break;
				case 5:
					grid.text = "图标";
					break;
				}
			}


		}

		private void textBox1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e) {
			string text = textBox1.TextBox.Text;
			if (e.KeyCode == Keys.Enter && text != "") {

				mItemList = new List<IItem>();
				
				int rankMask = 0;
				if (checkBoxRankD.Checked)
					rankMask |= 1<<1;
				if (checkBoxRankC.Checked)
					rankMask |= 1<<2;
				if (checkBoxRankB.Checked)
					rankMask |= 1<<3;
				if (checkBoxRankA.Checked)
					rankMask |= 1<<4;
				if (checkBoxRankS.Checked)
					rankMask |= 1<<5;
				if (checkBoxRankL.Checked)
					rankMask |= 1<<6;
				int job = mSelectedJob;

				TableEntry entry = mSelectedTableEntry;
				if (entry == null || string.IsNullOrEmpty(entry.path)) {
					foreach (TableEntry en in mTables) {
						if (string.IsNullOrEmpty(en.path))
							continue;
						Search(text, Util.GetTable(en.path), mItemList, rankMask, job);
					}
				} else {
					Search(text, Util.GetTable(entry.path), mItemList, rankMask, job);
				}
				if (mAdapter == null) {
					mAdapter = new ItemAdapter();
				} 
				mAdapter.SetItems(mItemList);
				listGridView1.SetAdapter(mAdapter);
				listGridView1.Invalidate();
			}
		}

		void Search(string text, Dntable itemTable, List<IItem> list, int rankMask, int job) {
			ItemFieldsInfo fieldInfo = new ItemFieldsInfo(itemTable);
			int c = 0;
			for (int r=0; r<itemTable.RecordCount; r++) {
				string s = Util.FindUIString(((int)itemTable[r, fieldInfo.nameField]));
				if (s != null) {
					if (fieldInfo.nameParamsField >= 0) {
						string nameParams = (string)itemTable[r, fieldInfo.nameParamsField];
						if (nameParams != "") {
							s = string.Format(s, Util.parseParams3(nameParams, out c));
						}
					}
					if (s.IndexOf(text, StringComparison.OrdinalIgnoreCase)>=0) {

						if (rankMask <= 0 || (rankMask&(1 << 1+(int)itemTable[r, 10])) != 0) {

							if (job<=0 || Util.JobCanAccepet(job, (string)itemTable[r, 9])) {
								IItem item = new Item(itemTable, r);
								list.Add(item);
							}
							
						}
					}
				}
			}
		}

		private void EquipmentStoreViewerForm_SizeChanged(object sender, EventArgs e) {
			listGridView1.Size = new Size(this.ClientSize.Width-20, this.ClientSize.Height-20-listGridView1.Top);
		}

		class ItemFieldsInfo {
			public int nameField = -1;
			public int nameParamsField = -1;
			public int limitLevelField = -1;
			public int needJobClassField = -1;
			public int rankField = -1;
			public int iconIndexField = -1;
			public int descriptionField = -1;
			public int descriptionParamsField = -1;
			public int stateFieldStart = -1;
			public int stateFieldEnd = -1;
			public int typeParam1Field = -1;
			public bool simpleState;
			public int enchantField = -1;
			public int exchangeTypeField = -1;
			public int typeParam2Field = -1;
			public int dragonJewelTypeField = -1;
			public int skillIdField = 1;

			public ItemFieldsInfo(Dntable table) {
				Regex stateFieldPettern = new Regex(@"^_State[\d]+$");
				for (int i=0; i<table.FieldCount; i++) {
					DntField field = table.GetField(i);
					if (nameField<0 && field.type==DntFieldType.Int32 && field.name=="_NameID") {
						nameField = i;
						if(field.uistring)
							nameParamsField = field.paramsIndex;
						continue;
					}
					if (limitLevelField<0 && field.type==DntFieldType.Int32 && field.name=="_LevelLimit") {
						limitLevelField = i;
						continue;
					}
					if (needJobClassField<0 && field.type==DntFieldType.String && field.name=="_NeedJobClass") {
						needJobClassField = i;
						continue;
					}
					if (rankField<0 && field.type==DntFieldType.Int32 && field.name=="_Rank") {
						rankField = i;
						continue;
					}
					if (iconIndexField<0 && field.type==DntFieldType.Int32 && field.name=="_IconImageIndex") {
						iconIndexField = i;
						continue;
					}
					if (descriptionField<0 && field.type==DntFieldType.Int32 && field.name=="_DescriptionID") {
						descriptionField = i;
						if (field.uistring)
							descriptionParamsField = field.paramsIndex;
						continue;
					}
					if (stateFieldStart<0 && field.type==DntFieldType.Int32 && field.name=="_State1") {
						stateFieldEnd = stateFieldStart = i;
						continue;
					}
					if (!simpleState && field.type==DntFieldType.String && field.name=="_StateValue1") {
						simpleState = true;
					}
					if (field.type==DntFieldType.Int32 && stateFieldPettern.IsMatch(field.name)) {
						stateFieldEnd = i;
						continue;
					}
					if (typeParam1Field<0 && field.type==DntFieldType.Int32 && field.name=="_TypeParam1") {
						typeParam1Field = i;
					}
					if (typeParam2Field<0 && field.type==DntFieldType.Int32 && field.name=="_TypeParam2") {
						typeParam2Field = i;
					}
					if (enchantField<0 && field.type==DntFieldType.Int32 && field.name=="_EnchantID") {
						enchantField = i;
					}
					if (exchangeTypeField<0 && field.type==DntFieldType.Int32 && field.name=="_ExchangeType") {
						exchangeTypeField = i;
					}
					if (dragonJewelTypeField<0 && field.type==DntFieldType.Int32 && field.name=="_dragonjeweltype") {
						dragonJewelTypeField = i;
					}
					if (skillIdField<0 && field.type==DntFieldType.Int32 && field.name=="_SkillID") {
						skillIdField = i;
					}
				}
			}
		}

		private class TableEntry {
			public string name;
			public string path;
			public TableEntry(string name, string path) {
				this.name = name;
				this.path = path;
			}

			public override string ToString() {
				return name;
			}
		}


		private void checkBox1_CheckedChanged(object sender, EventArgs e) {
			this.TopMost = (sender as CheckBox).Checked;
		}

		private void spriteButtom1_Click(object sender, EventArgs e) {
			mJobMenu.Show(spriteButtom1.PointToScreen(new Point(spriteButtom1.Width - 10, spriteButtom1.Height+2)));
		}

		private void spriteButtom2_Click(object sender, EventArgs e) {
			ContextMenuStrip menu = new ContextMenuStrip();
			menu.Renderer = new ContextMenuStripRenderer();
			EventHandler onclick = delegate(object s, EventArgs ea){
				SelectTable(((ToolStripItem)s).Tag as TableEntry);
			};
			foreach (TableEntry entry in mTables) {
				menu.Items.Add(entry.name, null, onclick).Tag = entry;
			}
			menu.Show(spriteButtom2.PointToScreen(new Point(spriteButtom2.Bottom - 10, spriteButtom2.Height+2)));
		}


		private ContextMenuStrip CreateJobSelectMenu() {
			ContextMenuStrip menu = new ContextMenuStrip();
			menu.Renderer = new ContextMenuStripRenderer();
			menu.Renderer.RenderItemImage += delegate(object s, ToolStripItemImageRenderEventArgs ea) {
				int jonIcon = Util.GetJobIconId((int)ea.Item.Tag);
				if (jonIcon >= 0)
					Util.DrawJobIconPvP(ea.Graphics, ea.ImageRectangle, jonIcon);
			};
			Dntable jobTable = DnResourceUtil.JobTable;
			Hashtable group = new Hashtable();
			EventHandler onClick = delegate(object s, EventArgs ea) {
				ToolStripDropDownItem item = (ToolStripDropDownItem)s;
				SelectJob((int)item.Tag);
				if (item.DropDownItems.Count>0)
					menu.Close();
			};
			menu.Items.Add("所有职业", null, onClick).Tag = 0;
			for (int r=0; r<jobTable.RecordCount; r++) {
				if ((bool)jobTable[r, "_Service"]) {
					AddJob(jobTable.GetKey(r), group, menu, onClick);
				}
			}
			return menu;
		}

		private ToolStripDropDownItem AddJob(int job, Hashtable group, ContextMenuStrip menu, EventHandler onClick) {
			if (group[job] != null)	// 已添加的职业
				return null;
			int parentJob = Util.GetParentJob(job);
			ToolStripDropDownItem item = null;

			if (parentJob <= 0) {
				group[job] = item = (ToolStripDropDownItem)menu.Items.Add(DnResourceUtil.GetJobName(job));
			} else if ((item = (ToolStripDropDownItem)group[parentJob]) != null)
				group[job] = item = (ToolStripDropDownItem)item.DropDownItems.Add(DnResourceUtil.GetJobName(job));
			else if ((item = AddJob(parentJob, group, menu, onClick)) != null) 
				group[job] = item = (ToolStripDropDownItem)item.DropDownItems.Add(DnResourceUtil.GetJobName(job));
			
			if (item != null) {
				item.Tag = job;
				item.Image = new Bitmap(10, 10);
				item.Click += onClick;
			}
			return item;
		}

		private void button1_Click_1(object sender, EventArgs e) {
			Close();
		}

		private void EquipmentStoreViewerForm_Paint(object sender, PaintEventArgs e) {
			//DrawingUtil.DrawOuterGrowText(e.Graphics, new Rectangle(10, 3, 100, 25), "装备仓库", new FontFamily("微软雅黑"), FontStyle.Regular, 12, Color.WhiteSmoke, Color.FromArgb(100, Color.White), 1, 2);
			//e.Graphics.DrawRectangle(mFormBorderPen, 0, 0, Width-1, Height-1);
		}

	}
}
